# -*- coding: utf-8 -*-
# -------------------------------------------------------------------------------
# @Create Time  : 2024/4/2 17:43
# @Author       : kony.xie
# @File Name    : getResources.py
# @Python Ver.  : Python 3.8.10
# @Description  : It is used to obtain server resources from Prometheus and generate html temporary files.
#                 Currently not in use.
# -------------------------------------------------------------------------------
import requests, time

class GetResources():
    def __init__(self, host, stime, etime, filename):
        # 配置prometheus访问地址
        self.host = 'http://' + host
        # 输出文件名
        self.filename = filename
        # 配置时间区间 %Y%m%d%H%M%S
        self.starttime = int(time.mktime(time.strptime(stime, "%Y%m%d%H%M%S")))
        self.endtime = int(time.mktime(time.strptime(etime, "%Y%m%d%H%M%S")))

    def createReport(self):
        if self.endtime <= (self.starttime+60):
            htmlres = "\n<h2>运行时间太短，无法获取监控资源</h2><br/>"
        else:
            # 获取node节点ip（list）
            nodeipdict = self.getnodeip(self.host, self.starttime, self.endtime)
            nodeiplist = []
            for x in nodeipdict['Linux']:
                nodeiplist.append(x)
            for x in nodeipdict['Win']:
                nodeiplist.append(x)
            if len(nodeiplist)==0:
                htmlres = "\n<h2>未获取到监控资源，请检查Prometheus配置</h2><br/>"
            else:
                # 获取cpu使用率(list #各个节点，#[0]时间[1]cpu使用率)
                cpuuse = self.getcpuuse(self.host, nodeipdict, self.starttime, self.endtime)
                # 获取mem使用率(list #各个节点，#[0]时间[1]cpu使用率)
                memuse = self.getmemuse(self.host, nodeipdict, self.starttime, self.endtime)
                diskread = self.getDiskRead(self.host, nodeipdict, self.starttime, self.endtime)
                diskwrite = self.getDiskWrite(self.host, nodeipdict, self.starttime, self.endtime)
                netRecv = self.getNetRecive(self.host, nodeipdict, self.starttime, self.endtime)
                netTran = self.getNetTran(self.host, nodeipdict, self.starttime, self.endtime)
                # 生成html
                htmlres = self.createHtml(nodeiplist, cpuuse, memuse, diskread, diskwrite, netRecv, netTran)
                # 整合到html报告
        result = self.addToHtml(htmlres, self.filename)
        return result
            
    def pronodeip(self, result):
        try:
            list = [item['metric']['instance'] for item in result['data']['result']]
        except:
            print(result)
        return list

    def getvalue(self, result):
        try:
            timelist = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(item[0])) for item in result['data']['result'][0]['values']]
        except Exception as e:
            print("No data response,pls check.")
            print(str(e))
        valuelist = [round(float(item[1]),5) for item in result['data']['result'][0]['values']]
        return timelist,valuelist

    def reqPrometheus(self, url):
        try:
            response = requests.get(url, timeout=5)
            resdict = eval(response.text)
        except:
            print("无法连接Prometheus，请检查")
            resdict = {}
        return resdict

    #拼接url
    def joinurl(self, nodeip, expr, starttime=None, endtime=None,dict = None):
        if dict:
            expr = expr % {'nodeip': nodeip}
        else:
            expr = expr % nodeip
        starttime, endtime, step = self.protime(starttime, endtime)
        url = "/api/v1/query_range?query=%s&start=%s&end=%s&step=%s&_=%s" % (expr, starttime, endtime, step, time.time() * 1000)
        return url

    def protime(self, starttime, endtime):
        # 间隔15秒采集一次
        resstep = 15
        duration_time = endtime - starttime
        # 时间超过86400秒(24小时)的时候，控制采集间隔，保持采集数量不超过5000
        if duration_time > 86400:
            resstep = round(duration_time/5000 + 5)
        return starttime, endtime, resstep

    def avg(self, list):
        sum = 0
        for x in list:
            sum = sum + x
        avg = sum/len(list)
        avg = round(avg, 2)
        return str(avg)

    def createHtml(self, nodeiplist, cpuuse, memuse, diskread, diskwrite, netRecv, netTran):
        Htmltmp = r"""
        <!DOCTYPE html>
        <html>
            <head>
                <meta charset="UTF-8"> 
                <title>测试报告</title>
                <style type="text/css">
                    body {
                        font:normal 13px verdana,arial,helvetica;
                        color:#000000;
                    }
                    table tr td, table tr th {
                        font-size: 13px;
                    }
                    table.details tr th{
                        color: #ffffff;
                        font-weight: bold;
                        text-align:center;
                        background:#2674a6;
                        white-space: nowrap;
                    }
                    table.details tr td{
                        background:#eeeee0;
                        white-space: nowrap;
                    }
                </style>
            </head>

            <body>
                <h1 style="text-align: center; color: #1ab394; font-size: 18px; font-weight: 700">资源使用</h1>
                <table width="100%%">
                    %s
                </table>
                <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%%">
                    <!-- 详细数据表格 -->
                    %s
                </table>
                <hr size="1" width="100%%" align="center"><br/>      
            </body>
        </html>
        """
        node_avg_list_table =""
        for idx in range(len(nodeiplist)):
            # 基本信息
            bascinfo = '''            
                <tr>
                    <td style="font-size:14px; text-align:center">监控时间：%s——%s</td>
                </tr>
                ''' % (cpuuse[nodeiplist[idx]][0][0], cpuuse[nodeiplist[idx]][0][-1])
            node_avg_list_table = node_avg_list_table + """<tr valign="top" class="">
                            <td>%s</td>
                            <td>%s%%</td>
                            <td>%s%%</td>
                            <td>%sKB/s</td>
                            <td>%sKB/s</td>
                            <td>%sKB/s</td>
                            <td>%sKB/s</td>
                        </tr>
            """ % (nodeiplist[idx], self.avg(cpuuse[nodeiplist[idx]][1]), self.avg(memuse[nodeiplist[idx]][1]),
                   self.avg(diskread[nodeiplist[idx]][1]), self.avg(diskwrite[nodeiplist[idx]][1]), self.avg(netRecv[nodeiplist[idx]][1]),
                   self.avg(netTran[nodeiplist[idx]][1]))

        tabledatanode = """<tr valign="top">
                <th>nodeIP</th>
                <th>CPU</th>
                <th>MEM</th>
                <th>DiskRead</th>
                <th>DiskWrtie</th>
                <th>NetDown</th>
                <th>NetUpload</th>
            </tr>
            %s\n""" % (node_avg_list_table)
        
        Htmlres = Htmltmp % (bascinfo, tabledatanode)
        return Htmlres

    # 监控资源结果写入原html文件
    def addToHtml(self, htmlres, filename = None):
        with open(filename, 'a+', encoding='UTF-8') as addfile:
            addfile.write(htmlres)
            addfile.seek(0)
            return addfile.read()

    # 获取node节点ip
    def getnodeip(self, host, starttime=None,endtime=None, *args,**kwargs):
        result ={'Linux':[], 'Win':[]}
        starttime, endtime, step = self.protime(starttime, endtime)
        # 获取linxu节点
        url = host + '/api/v1/query_range?query=node_exporter_build_info&start=%s&end=%s&step=%s&_=%s' % (starttime, endtime, step, time.time()*1000)
        data = self.reqPrometheus(url)
        if len(data) > 0:
            result['Linux'] = self.pronodeip(data)
        # 获取windows节点
        urlwindows = host + '/api/v1/query_range?query=windows_exporter_build_info&start=%s&end=%s&step=%s&_=%s' % (starttime, endtime, step, time.time()*1000)
        data = self.reqPrometheus(urlwindows)
        if len(data) > 0:
            result['Win'] = self.pronodeip(data)
        return result

    # 获取cpu使用率
    def getcpuuse(self, host, nodeipdict, starttime=None, endtime=None, *args,**kwargs):
        result = {}
        # Linux系统
        if len(nodeipdict['Linux']) > 0:
            expr = '100-(avg(irate(node_cpu_seconds_total{instance="%s",mode=\"idle\"}[1m])))*100'
            for nodeip in nodeipdict['Linux']:
                url = host + self.joinurl(nodeip,expr,starttime,endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        # Win系统
        if len(nodeipdict['Win']) > 0:
            expr = '100-(avg(irate(windows_cpu_time_total{instance="%s",mode=\"idle\"}[1m])) * 100)'
            for nodeip in nodeipdict['Win']:
                url = host + self.joinurl(nodeip,expr,starttime,endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        return result

    # 获取内存使用率
    def getmemuse(self, host, nodeipdict, starttime=None, endtime=None, *args,**kwargs):
        result={}
        # Linux系统
        if len(nodeipdict['Linux']) > 0:
            expr = '((node_memory_MemTotal_bytes{instance="%(nodeip)s"} - node_memory_MemFree_bytes{instance="%(nodeip)s"} ' \
                   '- node_memory_Buffers_bytes{instance="%(nodeip)s"} - node_memory_Cached_bytes{instance="%(nodeip)s"}) ' \
                   '/ (node_memory_MemTotal_bytes{instance="%(nodeip)s"} )) * 100'
            for nodeip in nodeipdict['Linux']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime, 1)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        # Win系统
        if len(nodeipdict['Win']) > 0:
            expr = '100.0 - 100 * windows_os_physical_memory_free_bytes{instance="%(nodeip)s"} / windows_cs_physical_memory_bytes{instance="%(nodeip)s"}'
            for nodeip in nodeipdict['Win']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime, 1)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        return result

    # 获取磁盘读
    def getDiskRead(self, host, nodeipdict, starttime=None,endtime=None, *args,**kwargs):
        result={}
        # Linux系统
        if len(nodeipdict['Linux']) > 0:
            expr = 'max(irate(node_disk_read_bytes_total{instance="%s"}[1m]))/1024'
            for nodeip in nodeipdict['Linux']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        # Win系统
        if len(nodeipdict['Win']) > 0:
            expr = 'max(irate(windows_logical_disk_read_bytes_total{instance="%s"}[1m]))/1024'
            for nodeip in nodeipdict['Win']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        return result

    def getDiskWrite(self, host, nodeipdict, starttime=None,endtime=None, *args,**kwargs):
        result={}
        # Linux系统
        if len(nodeipdict['Linux']) > 0:
            expr = 'max(irate(node_disk_written_bytes_total{instance="%s"}[1m]))/1024'
            for nodeip in nodeipdict['Linux']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        # Win系统
        if len(nodeipdict['Win']) > 0:
            expr = 'max(irate(windows_logical_disk_write_bytes_total{instance="%s"}[1m]))/1024'
            for nodeip in nodeipdict['Win']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        return result

    def getNetRecive(self, host, nodeipdict, starttime=None,endtime=None, *args, **kwargs):
        result={}
        if len(nodeipdict['Linux']) > 0:
            for nodeip in nodeipdict['Linux']:
                expr = 'max(irate(node_network_receive_bytes_total{instance="%s"}[1m]))/1024'
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        if len(nodeipdict['Win']) > 0:
            expr = 'max(irate(windows_net_bytes_received_total{instance="%s"}[1m]))/1024'
            for nodeip in nodeipdict['Win']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        return result

    def getNetTran(self, host, nodeipdict, starttime=None,endtime=None, device=None, *args,**kwargs):
        result={}
        if len(nodeipdict['Linux']) > 0:
            for nodeip in nodeipdict['Linux']:
                expr = 'max(irate(node_network_transmit_bytes_total{instance="%s"}[1m]))/1024'
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        if len(nodeipdict['Win']) > 0:
            expr = 'max(irate(windows_net_bytes_sent_total{instance="%s"}[1m]))/1024'
            for nodeip in nodeipdict['Win']:
                url = host + self.joinurl(nodeip, expr, starttime, endtime)
                data = self.reqPrometheus(url)
                result[nodeip] = self.getvalue(data)
        return result
